package edu.northwestern.cbits.purple_robot_manager.probes.builtin;
import java.util.ArrayList;
import org.json.JSONObject;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
import android.preference.CheckBoxPreference;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.provider.Settings;
import android.support.v4.content.ContextCompat;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.LinearLayout;
import edu.northwestern.cbits.purple_robot_manager.R;
import edu.northwestern.cbits.purple_robot_manager.logging.LogManager;
import edu.northwestern.cbits.purple_robot_manager.logging.SanityManager;
import edu.northwestern.cbits.purple_robot_manager.probes.Probe;
public class TouchEventsProbe extends Probe
{
private static final String ENABLED = "config_probe_touch_events_enabled";
private static final boolean DEFAULT_ENABLED = false;
private Context _context = null;
private View _overlay = null;
private final ArrayList<Long> _timestamps = new ArrayList<>();
private long _lastTouch = 0;
@Override
public String getPreferenceKey() {
return "built_in_touch_events";
}
@Override
public String name(Context context)
{
return "edu.northwestern.cbits.purple_robot_manager.probes.builtin.TouchEventsProbe";
}
@Override
public String title(Context context)
{
return context.getString(R.string.title_touch_events_probe);
}
@Override
public String probeCategory(Context context)
{
return context.getResources().getString(R.string.probe_misc_category);
}
@Override
public void enable(Context context)
{
SharedPreferences prefs = Probe.getPreferences(context);
Editor e = prefs.edit();
e.putBoolean(TouchEventsProbe.ENABLED, true);
e.commit();
}
@Override
public void disable(Context context)
{
SharedPreferences prefs = Probe.getPreferences(context);
Editor e = prefs.edit();
e.putBoolean(TouchEventsProbe.ENABLED, false);
e.commit();
}
@Override
public boolean isEnabled(final Context context)
{
final SharedPreferences prefs = Probe.getPreferences(context);
boolean enabled = super.isEnabled(context);
if (this._context == null)
this._context = context.getApplicationContext();
if (enabled)
enabled = prefs.getBoolean(TouchEventsProbe.ENABLED, TouchEventsProbe.DEFAULT_ENABLED);
if (enabled)
{
WindowManager wm = (WindowManager) this._context.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
synchronized (wm)
{
boolean canDraw = (ContextCompat.checkSelfPermission(context, "android.permission.SYSTEM_ALERT_WINDOW") == PackageManager.PERMISSION_GRANTED);
if (canDraw == false && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
canDraw = Settings.canDrawOverlays(context);
if (canDraw)
{
if (this._overlay == null)
{
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.format = PixelFormat.TRANSLUCENT;
params.height = 1; // WindowManager.LayoutParams.MATCH_PARENT;
params.width = 1; // WindowManager.LayoutParams.MATCH_PARENT;
params.gravity = Gravity.RIGHT | Gravity.BOTTOM;
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
final TouchEventsProbe me = this;
this._overlay = new LinearLayout(this._context.getApplicationContext());
this._overlay.setBackgroundColor(android.graphics.Color.argb(0, 255, 255, 255));
this._overlay.setHapticFeedbackEnabled(true);
this._overlay.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View arg0, MotionEvent event)
{
me._lastTouch = System.currentTimeMillis();
me._timestamps.add(me._lastTouch);
return false;
}
});
if (Looper.myLooper() == null)
Looper.prepare();
try
{
wm.addView(this._overlay, params);
}
catch (IllegalStateException e)
{
LogManager.getInstance(context).logException(e);
}
}
SanityManager.getInstance(context).clearPermissionAlert("android.permission.SYSTEM_ALERT_WINDOW");
}
else
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Runnable r = new Runnable() {
@Override
public void run() {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + context.getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
SanityManager.getInstance(context).clearPermissionAlert("android.permission.SYSTEM_ALERT_WINDOW");
}
};
SanityManager.getInstance(context).addPermissionAlert(this.name(context), "android.permission.SYSTEM_ALERT_WINDOW", context.getString(R.string.rationale_system_alert_probe), r);
}
}
}
if (this._lastTouch != 0)
{
long now = System.currentTimeMillis();
Bundle bundle = new Bundle();
bundle.putString("PROBE", this.name(context));
bundle.putLong("TIMESTAMP", now / 1000);
bundle.putLong("LAST_TOUCH_DELAY", now - this._lastTouch);
bundle.putInt("TOUCH_COUNT", this._timestamps.size());
this.transmitData(context, bundle);
this._timestamps.clear();
}
return true;
}
else if (this._overlay != null)
{
WindowManager wm = (WindowManager) this._context.getSystemService(Context.WINDOW_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
if (this._overlay.isAttachedToWindow())
wm.removeView(this._overlay);
}
this._overlay = null;
}
return false;
}
@Override
public String summarizeValue(Context context, Bundle bundle)
{
int count = (int) bundle.getDouble("TOUCH_COUNT");
long delay = (long) bundle.getDouble("LAST_TOUCH_DELAY");
if (count == 1)
return context.getResources().getString(R.string.summary_touch_events_probe_single, delay);
return context.getResources().getString(R.string.summary_touch_events_probe, count, delay);
}
@Override
@SuppressWarnings("deprecation")
public PreferenceScreen preferenceScreen(Context context, PreferenceManager manager)
{
PreferenceScreen screen = super.preferenceScreen(context, manager);
screen.setTitle(this.title(context));
screen.setSummary(R.string.summary_touch_events_probe_desc);
CheckBoxPreference enabled = new CheckBoxPreference(context);
enabled.setTitle(R.string.title_enable_probe);
enabled.setKey(TouchEventsProbe.ENABLED);
enabled.setDefaultValue(TouchEventsProbe.DEFAULT_ENABLED);
screen.addPreference(enabled);
return screen;
}
@Override
public String summary(Context context)
{
return context.getString(R.string.summary_touch_events_probe_desc);
}
}